package top.fkxuexi.smartwork.core;

import top.fkxuexi.smartwork.MetaEntity.ColMeta;
import top.fkxuexi.smartwork.MetaEntity.ForeignCelMeta;
import top.fkxuexi.smartwork.MetaEntity.TableMeta;
import top.fkxuexi.smartwork.config.SmkConfig;
import top.fkxuexi.smartwork.tools.DbUtils;
import top.fkxuexi.smartwork.tools.StyleConvert;
import top.fkxuexi.smartwork.tools.TypeEnum;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MySQLMetaParse implements MetaParse {

    private SmkConfig config;


    public MySQLMetaParse(SmkConfig config){
        this.config = config;
    }

    /**
     * @return 返回指定连接中的数据库的所有的表
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    @Override
    public List<String> getAllTable() throws SQLException {
        Connection conn = DbUtils.getConn(config);
        PreparedStatement pst = conn.prepareStatement(ParseSQL.GET_ALL_TABLE_META);
        pst.setString(1,DbUtils.getDbName(config.getUrl()));
        ResultSet rst = pst.executeQuery();
        List<String> list = new ArrayList<>();
        while (rst.next()){
            list.add(rst.getString("TABLE_NAME"));
        }
        return list;
    }

    @Override
    public List<TableMeta> getAllTaleMeta() throws SQLException {
        List<String> list = getAllTable();
        String[] t = new String[]{};
        String[] tables = list.toArray(t);
        return getTableMeta(tables);
    }

    @Override
    public List<TableMeta> getTableMeta(String[] tableNames) throws SQLException {

        List<TableMeta> tableMetaList = new ArrayList<>();
        for (String tableName : tableNames) {
            tableMetaList.add(getSingleTableMeta(tableName));
        }
        return tableMetaList;
    }

    private TableMeta getSingleTableMeta(String tableName) throws SQLException {
        TableMeta tableMeta = new TableMeta();
        //设置表名
        tableMeta.setDbName(tableName);
        // 设置java风格的表名
        tableMeta.setJavaDbName(StyleConvert.underline2hump(tableName,true));
        tableMeta.setKeySize(0);

        Connection conn = DbUtils.getConn(config);
        String dbName = DbUtils.getDbName(config.getUrl());
        PreparedStatement tableMetaPst = conn.prepareStatement(ParseSQL.GET_PARSE_TABLE_META);
        tableMetaPst.setString(1,dbName);
        tableMetaPst.setString(2,tableName);
        ResultSet tableMetaRst = tableMetaPst.executeQuery();
        // 设置表的说明字段
        while (tableMetaRst.next()){
            tableMeta.setComment(tableMetaRst.getString("TABLE_COMMENT"));
        }
        // 这个是获取表的指定的元数据信息
        PreparedStatement colMetaPsd = conn.prepareStatement(ParseSQL.PARSE_TABLE_META);
        colMetaPsd.setString(1,dbName);
        colMetaPsd.setString(2,tableName);
        ResultSet colMetaRst = colMetaPsd.executeQuery();

        List<ColMeta> colMetaList = new ArrayList<>();
        List<ForeignCelMeta> foreignCelMetaList = new ArrayList<>();
        List<String> importList = new ArrayList<>();
        ColMeta colMeta; ForeignCelMeta foreignCelMeta = null;
        while (colMetaRst.next()){
            // 获取数据取得的元数据信息
            String dbAttrName = colMetaRst.getString("COLUMN_NAME");
            String dbAttrType = colMetaRst.getString("DATA_TYPE");
            String colKey = colMetaRst.getString("COLUMN_KEY");
            String defaultValue = colMetaRst.getString("COLUMN_DEFAULT");
            String comment = colMetaRst.getString("COLUMN_COMMENT");
            String extra = colMetaRst.getString("EXTRA");

            String javaAttrName = StyleConvert.underline2hump(dbAttrName);
            TypeEnum typeEnum = TypeEnum.valueof(dbAttrType);
            String javaAttrType = typeEnum.getJavaType();
            String importStr = typeEnum.getImportStr();

            colMeta = new ColMeta(javaAttrName,dbAttrName,dbAttrType,javaAttrType,defaultValue,comment,false,false);

            if (colKey.equalsIgnoreCase("MUL")){
                // 外键
                PreparedStatement fkPst = conn.prepareStatement(ParseSQL.PARSE_TABLE_KEY_META);
                fkPst.setString(1,tableName);
                fkPst.setString(2,dbAttrName);
                ResultSet fkRst = fkPst.executeQuery();
                // 这里无需遍历，因为只一个字段是不可能会产生多个外键的
                while (fkRst.next()){
                    String refTableName = fkRst.getString("referenced_table_name");
                    String refFiledName = fkRst.getString("referenced_column_name");

                    String refTableJavaName = StyleConvert.underline2hump(refTableName,true);
                    String refFiledJavaName = StyleConvert.underline2hump(refFiledName);

                    foreignCelMeta = new ForeignCelMeta(javaAttrName,dbAttrName,dbAttrType,javaAttrType,defaultValue,comment,
                            false,false,refTableName,refTableJavaName,refFiledName,refFiledJavaName);
                    foreignCelMetaList.add(foreignCelMeta);
                }
            }
            if("PRI".equalsIgnoreCase(colKey)){
                // 主键
                colMeta.setKey(true);
                if ("auto_increment".equalsIgnoreCase(extra)){
                    colMeta.setAutoIncrease(true);
                }
                tableMeta.setKeySize(tableMeta.getKeySize() + 1);
            }
            colMetaList.add(colMeta);
            if (importStr != null ){
                importList.add(importStr);
            }

        }

        tableMeta.setColMetaList(colMetaList);
        tableMeta.setForeignCelMetaList(foreignCelMetaList);
        tableMeta.setImportList(importList);
        return tableMeta;
    }

}
